#include <stdio.h>
#include <stdbool.h>
#include <alsa/asoundlib.h>
#include <gpiod.h>
#include <unistd.h>
#include <stdlib.h>

#define GPIO_LINE_K2 7  // 定义K2按钮的GPIO线编号
#define GPIO_LINE_K3 8 // 定义K3按钮的GPIO线编号

// 获取音频回放通道音量
//card：声卡名称
//selem：控制项名称
//返回值： 当前音量
int get_playback_volume(const char* card, const char* selem) {
    int err;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;

    // 打开混音器
    if ((err = snd_mixer_open(&handle, 0)) < 0) {
        fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err));
        return err;
    }

    // 附加控制接口到混音器
    if ((err = snd_mixer_attach(handle, card)) < 0) {
        fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 注册混音器
    if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
        fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 加载混音器元素
    if ((err = snd_mixer_load(handle)) < 0) {
        fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 分配简单元素ID
    snd_mixer_selem_id_alloca(&sid);

    // 设置简单元素的名称
    snd_mixer_selem_id_set_name(sid, selem);

    // 查找简单元素
    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
    if (!elem) {
        fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0);
        snd_mixer_close(handle);
        return -ENOENT;
    }

    // 获取回放通道音量
    long volume = 0;
    if ((err = snd_mixer_selem_get_playback_volume(elem, 0, &volume)) < 0) {
        fprintf(stderr, "Unable to get playback volume: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 关闭混音器
    snd_mixer_close(handle);

    return volume; // 成功返回音量
}

// 设置音频回放通道音量
//card：声卡名称
//selem：控制项名称
//volume：设置音量
//返回值： 成功返回设置后音量值,失败返回错误码
int set_playback_volume(const char* card, const char* selem, long volume) {
    int err;
    snd_mixer_t *handle;
    snd_mixer_selem_id_t *sid;

    // 打开混音器
    if ((err = snd_mixer_open(&handle, 0)) < 0) {
        fprintf(stderr, "Mixer %s open error: %s\n", card, snd_strerror(err));
        return err;
    }

    // 附加控制接口到混音器
    if ((err = snd_mixer_attach(handle, card)) < 0) {
        fprintf(stderr, "Mixer attach %s error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 注册混音器
    if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
        fprintf(stderr, "Mixer register error: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 加载混音器元素
    if ((err = snd_mixer_load(handle)) < 0) {
        fprintf(stderr, "Mixer %s load error: %s\n", card, snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 分配简单元素ID
    snd_mixer_selem_id_alloca(&sid);

    // 设置简单元素的名称
    snd_mixer_selem_id_set_name(sid, selem);

    // 查找简单元素
    snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
    if (!elem) {
        fprintf(stderr, "Unable to find simple control '%s',%i\n", selem, 0);
        snd_mixer_close(handle);
        return -ENOENT;
    }

    // 获取音量范围
    long min, max;
    if ((err = snd_mixer_selem_get_playback_volume_range(elem, &min, &max)) < 0)
    {
        fprintf(stderr, "Unable to get capture volume range: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }
    
    if (volume < min)
    {
        volume = min;
    }

    if (volume > max)
    {
        volume = max;
    }

    // 设置回放通道音量
    if ((err = snd_mixer_selem_set_playback_volume_all(elem, volume)) < 0) {
        fprintf(stderr, "Unable to set playback volume: %s\n", snd_strerror(err));
        snd_mixer_close(handle);
        return err;
    }

    // 关闭混音器
    snd_mixer_close(handle);

    return volume; // 成功
}

int main(void) {
    struct gpiod_chip *chip;      // 定义指向GPIO芯片的指针
    struct gpiod_line *line_k2;   // 定义指向K2按钮GPIO线的指针
    struct gpiod_line *line_k3;   // 定义指向K3按钮GPIO线的指针
    int value_k2, last_value_k2;  // 当前和上一次的K2按钮值
    int value_k3, last_value_k3;  // 当前和上一次的K3按钮值
    long volume;                  // 当前音量

    // 打开GPIO芯片
    chip = gpiod_chip_open_by_label("GPIOF");
    if (!chip) {
        perror("打开GPIO芯片失败");
        return 1;
    }

    // 获取K2按钮的GPIO线
    line_k2 = gpiod_chip_get_line(chip, GPIO_LINE_K2);
    if (!line_k2) {
        perror("获取K2按钮GPIO线失败");
        gpiod_chip_close(chip);
        return 1;
    }

    // 获取K3按钮的GPIO线
    line_k3 = gpiod_chip_get_line(chip, GPIO_LINE_K3);
    if (!line_k3) {
        perror("获取K3按钮GPIO线失败");
        gpiod_chip_close(chip);
        return 1;
    }

    // 将K2按钮GPIO线设置为输入模式
    if (gpiod_line_request_input(line_k2, "key_k2")) {
        perror("请求K2按钮GPIO线输入模式失败");
        gpiod_chip_close(chip);
        return 1;
    }

    // 将K3按钮GPIO线设置为输入模式
    if (gpiod_line_request_input(line_k3, "key_k3")) {
        perror("请求K3按钮GPIO线输入模式失败");
        gpiod_chip_close(chip);
        return 1;
    }

    // 获取初始的按钮状态
    last_value_k2 = gpiod_line_get_value(line_k2);
    last_value_k3 = gpiod_line_get_value(line_k3);

    // 获取当前音量
    volume = get_playback_volume("hw:0", "Analog");

    // 无限循环检测按钮状态变化
    while (1) {
        // 获取K2按钮的当前状态
        value_k2 = gpiod_line_get_value(line_k2);
        
        // 获取K3按钮的当前状态
        value_k3 = gpiod_line_get_value(line_k3);
        
        // 检测K2按钮状态变化
        if (value_k2 != last_value_k2) {
            // 按下K2按钮
            if (value_k2 == 0) {
                printf("K2 pressed\n");
                volume += 5; // 增加音量
                //volume = set_playback_volume("hw:0", "Analog", volume);
                printf("Old Playback Vol: %d\n", get_playback_volume("hw:0", "Analog"));
                printf("New Playback Vol: %ld\n", set_playback_volume("hw:0", "Analog", volume));
            }
            // 更新K2按钮状态
            last_value_k2 = value_k2;
        }
        
        // 检测K3按钮状态变化
        if (value_k3 != last_value_k3) {
            // 按下K3按钮
            if (value_k3 == 0) {
                printf("K3 pressed\n");
                volume -= 5; // 减少音量
                //volume = set_playback_volume("hw:0", "Analog", volume);
                printf("Old Playback Vol: %d\n", get_playback_volume("hw:0", "Analog"));
                printf("New Playback Vol: %ld\n", set_playback_volume("hw:0", "Analog", volume));
            }
            // 更新K3按钮状态
            last_value_k3 = value_k3;
        }

        // 延时100毫秒，防止检测过于频繁
        usleep(100000);
    }

    // 释放GPIO线资源
    gpiod_line_release(line_k2);
    gpiod_line_release(line_k3);

    // 关闭GPIO芯片
    gpiod_chip_close(chip);
    
    return 0;
}